package com.rybbaby.tss.platform.websocket.handler;

import com.rybbaby.tss.core.utils.JSONUtil;
import com.rybbaby.tss.platform.websocket.pojo.WebSocketMessageInfo;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;

import java.io.IOException;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

/**
 * @author 谢进伟
 * @description WebScoket配置处理器
 * @createDate 2017-02-14 下午9:11:51
 */
@Component
public class MsgWebSocketHandler implements WebSocketHandler {

    public static final Map<Object, WebSocketSession> userSocketSessionMap;
    public Logger logger = Logger.getLogger(MsgWebSocketHandler.class);

    static {
        userSocketSessionMap = new HashMap<>();
    }

    /**
     * 建立连接后
     */
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        Object uid = session.getAttributes().get("uid");
        if (userSocketSessionMap.get(uid) == null) {
            userSocketSessionMap.put(uid, session);
        }
    }

    /**
     * 消息处理，在客户端通过Websocket API发送的消息会经过这里，然后进行相应的处理
     */
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        if (message.getPayloadLength() == 0)
            return;
        WebSocketMessageInfo msg = JSONUtil.jsonToBean(message.getPayload().toString(), WebSocketMessageInfo.class);
        msg.setSendTime(new Timestamp(System.currentTimeMillis()));
        sendMessageToUser(msg.getTo(), new TextMessage(JSONUtil.toJsonStr(msg)));
    }

    /**
     * 消息传输错误处理
     */
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        if (session.isOpen()) {
            session.close();
        }
        removeUser(session);
    }

    /**
     * 关闭连接后
     */
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        logger.info("Websocket:" + session.getId() + "已经关闭");
        removeUser(session);
    }

    /**
     * 移除指定会话
     *
     * @param session
     */
    private void removeUser(WebSocketSession session) {
        Iterator<Entry<Object, WebSocketSession>> it = userSocketSessionMap.entrySet().iterator();
        // 移除Socket会话
        while (it.hasNext()) {
            Entry<Object, WebSocketSession> entry = it.next();
            if (entry.getValue().getId().equals(session.getId())) {
                userSocketSessionMap.remove(entry.getKey());
                logger.info("Socket会话已经移除:用户ID" + entry.getKey());
                break;
            }
        }
    }

    public boolean supportsPartialMessages() {
        return false;
    }

    /**
     * 给所有在线用户发送消息
     *
     * @param message
     * @throws IOException
     */
    public void broadcast(final TextMessage message) throws IOException {
        Iterator<Entry<Object, WebSocketSession>> it = userSocketSessionMap.entrySet().iterator();
        // 多线程群发
        while (it.hasNext()) {

            final Entry<Object, WebSocketSession> entry = it.next();

            if (entry.getValue().isOpen()) {
                // entry.getValue().sendMessage(message);
                new Thread(new Runnable() {

                    public void run() {
                        try {
                            if (entry.getValue().isOpen()) {
                                entry.getValue().sendMessage(message);
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }

                }).start();
            }

        }
    }

    /**
     * 给某个用户发送消息
     *
     * @param toUserId
     * @param message
     * @throws IOException
     */
    public void sendMessageToUser(String toUserId, TextMessage message) throws IOException {
        WebSocketSession session = userSocketSessionMap.get(toUserId);
        if (session != null && session.isOpen()) {
            session.sendMessage(message);
        }
    }

}
